
Research
Security News
Lazarus Strikes npm Again with New Wave of Malicious Packages
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
@comate/plugin-shared-internals
Advanced tools
本包@comate/plugin-schema
提供与插件系统有关的各种共享类型、常量及常用读写能力。
由于整体是多进程的体系,不能像普通函数一样进行直接调用,因此制定了一套通信和会话的能力,以满足以下要求:
Promise
的形态进行一次调用,插件执行完成前,Engine端可以通过简单的await
阻塞自身的逻辑。社区中普遍使用的RPC封装方案如async-call-rpc都只能解决第一个问题,因此我们自己实现了一套方案。
ChannelImplement
:指一个原本已经存在的能够进行通信的对象,这个对象必须有一个message
事件和一个send
方法。从定义可以看出来,一个进程就是典型的ChannelImplement
对象,也可以通过WebSocket
等方式来实现这个接口。Channel
:对ChannelImplement
做一次封装,通过对message
和send
的处理,能够管理会话。其本质是使用sessionId
关联各种message
到同一个会话中。Session
:代表一次会话,可以由Channel#startSession
主动创建,也可以在一条有全新的sessionId
的消息到达时被动创建。所有的发送和接收消息都是在Session
对象中处理的,即发送消息的方法、接收消息的事件监听,都是通过继承Session
类来做的。 ┌───────┐ ┌───────┐
│Session│ │Session│
└───────┘ └───────┘
┌────────────────┬─────────┐ ┌─────────┬────────────────┐
│ │ │ │ │ │
│ │ ├────────►│ │ │
│ │ │ │ │ │
│ Engine Process │ Channel │ │ Channel │ Plugin Process │
│ │ │ │ │ │
│ │ │◄────────┤ │ │
│ │ │ │ │ │
└────────────────┴─────────┘ └─────────┴────────────────┘
┌───────┐ ┌───────┐
│Session│ │Session│
└───────┘ └───────┘
正常的使用方法是写2个类,一个继承Session
并定义一系列的事件监听和发送方法,一个继承Channel
并重写createSession
方法返回自己的Session
子类。
对于Session
的子类:
PayloadMap
,它的键是你需要监听的action
常量,值是对应的payload
的类型。class extends Session<PayloadMap>
。initializeListeners
方法,先调用super.initializeListeners()
,再用setListener
方法监听不同的消息action
,TypeScript会自动推导出来payload
类型。Session
类是被其它功能使用的,那么添加一系列方法,每个方法是对send
的调用,用来发送指定类型的消息。Session
实现,你可以使用forwardMessageToParent
方法透传消息到父会话中。interface GreetingPayload {
name: string;
text: string;
}
interface GoodbyePayload {
name: string;
}
const ACTION_GREETING = 'GREETING';
const ACTION_GOODBYE = 'GOODBYE';
interface PayloadMap {
[ACTION_GREETING]: GreetingPayload;
[ACTION_GOODBYE]: GoodbyePayload;
}
class MySession extends Session<PayloadMap> {
sendGift(price: number) {
this.send({action: 'SEND_GIFT', payload: {price}});
}
protected initializeListeners() {
super.initializeListeners();
this.setListener(
ACTION_GREETING,
payload => console.log(`Greeting from ${payload.name}: ${payload.text}`)
);
this.setListener(
ACTION_GOODBYE,
payload => console.log(`${payload.name} leaves`)
);
}
}
随后,实现自己的Channel
类型,继承时通过泛型指定自己的Session
子类,只需要createSession
方法即可:
class MyChannel extends Channel<MySession> {
protected createSession(init: SessionInit) {
return new MySession(init, this.implement);
}
}
由于Session
只能由Channel
创建,因此如果你的Session
实现需要很多其它的依赖,就要先在Channel
构造函数中获取,再通过createSession
传给Session
子类。
作为主动调用方,使用Channel#startSession
可以启动一个会话并发送一个消息过去,这个方法接收一个sessionId
字符串(使用UUID即可)或者一个父的Session
对象,会返回Promise
直到会话结束(收到SESSION_FINISH
消息)。
如果调用startSession
时传的是一个父Session
对象,那么2个会话就会建立父子关系,部分特殊的消息会由子向父的透传。
在调用startSession
后,指定的消息被发送到接收端(例如子进程的Channel
),在收到第一条有全新的sessionId
时,Channel
会创建一个Session
对象并处理这条消息(对应setListener
监听的回调函数)。在处理中可以用send
、log
等方法发消息回到调用子(如主进程的Channel
)。
所有通过Session
对象的log
和send
发送的消息,都会带上对应的sessionId
,以便将所有的信息关联起来。
对于特殊的内置消息类型(当前仅LOG
),它们默认会向父会话透传,即子会话的日志最终只在顶层处理,中间层不管理日志。
FAQs
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
Security News
Socket CEO Feross Aboukhadijeh discusses the open web, open source security, and how Socket tackles software supply chain attacks on The Pair Program podcast.
Security News
Opengrep continues building momentum with the alpha release of its Playground tool, demonstrating the project's rapid evolution just two months after its initial launch.